package jtt808

import (
	"fmt"
	"github.com/axgle/mahonia"
	"strconv"
	"strings"
	"sync/atomic"
)

func ToGBK(s string) string {
	dec := mahonia.NewEncoder("GBK")
	return dec.ConvertString(s)
}

func ToUint16(v []byte) uint16 {
	return uint16(v[0])*256 + uint16(v[1])
}

func ToUint16Little(v []byte) uint16 {
	return uint16(v[1])*256 + uint16(v[0])
}

func FromUint16(v uint16) []byte {
	res := make([]byte, 2)
	res[1] = byte(v % 256)
	res[0] = byte(v / 256)
	return res
}

func ToUint32(v []byte) uint32 {
	return uint32(v[0])*256*256*256 + uint32(v[1])*256*256 + uint32(v[2])*256 + uint32(v[3])
}
func ToUint32Little(v []byte) uint32 {
	return uint32(v[3])*256*256*256 + uint32(v[2])*256*256 + uint32(v[1])*256 + uint32(v[0])
}

func FromUint32(v uint32) []byte {
	res := make([]byte, 4)
	res[3] = byte(v % 256)
	v = v / 256
	res[2] = byte(v % 256)
	v = v / 256
	res[1] = byte(v % 256)
	res[0] = byte(v / 256)
	return res
}

// 将不固定长度的字节转换成整数 大端
func ToInt(v []byte) int {
	i := 0
	for _, b := range v {
		i = i*256 + int(b)
	}
	return i
}

// 多个切片按照顺序合并一起
func SlicesAppend(bs ...[]byte) []byte {
	var all []byte
	for _, b := range bs {
		all = append(all, b...)
	}
	return all
}

/*
*
s:字符串
n:转存到字节切片的长度
字符串转存到指定长度的字节数组
如果字符串转的字节长度 大于字节数组限定长度 则截取最后指定长度字节数
如果字符串转的字节长度l 小于字节数组限定长度，则拷贝bf的后面l个字节
*/
func StrToBytes(s string, n int) []byte {
	bf := make([]byte, n)
	b := []byte(s)
	l := len(b)
	if l > n {
		copy(bf, b[l-n:l])
	} else {
		copy(bf[n-l:], b)
	}
	return bf
}

func Bcd2Number(bcd []byte) string {
	var number string
	for _, i := range bcd {
		number += fmt.Sprintf("%02X", i)
	}
	pos := strings.LastIndex(number, "F")
	if pos == 8 {
		return "0"
	}
	return number[pos+1:]
}

// 转bcd码
func Number2bcd(number string) []byte {
	var rNumber = number
	for i := 0; i < 8-len(number); i++ {
		rNumber = "f" + rNumber
	}
	bcd := Hex2Byte(rNumber)
	return bcd
}

func Hex2Byte(str string) []byte {
	slen := len(str)
	bHex := make([]byte, len(str)/2)
	ii := 0
	for i := 0; i < len(str); i = i + 2 {
		if slen != 1 {
			ss := string(str[i]) + string(str[i+1])
			bt, _ := strconv.ParseInt(ss, 16, 32)
			bHex[ii] = byte(bt)
			ii = ii + 1
			slen = slen - 2
		}
	}
	return bHex
}

/*
*设置包序号 从1 开始
 */
func GetSerialNumber() uint16 {
	v := atomic.LoadUint32(&PacketSeq)
	//如果取值未65535 则设置为0 重新递增包序号
	if v == 65534 {
		atomic.StoreUint32(&PacketSeq, 0)
	} else {
		atomic.AddUint32(&PacketSeq, 1)
	}
	return uint16(PacketSeq)
}
